﻿namespace _24_Hour_Blogger.Services
{
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Linq;
    using _24_Hour_Blogger.Exceptions;
    using _24_Hour_Blogger.Models;
    using _24_Hour_Blogger.Models.Content;
    using _24_Hour_Blogger.Models.Repository;
    using _24_Hour_Blogger.ViewModels.Content;
    using _24_Hour_Blogger.ViewModels.Repository;
    using Microsoft.WindowsAzure.Storage.Blob;

    public class AzureMediaManager
    {
        private const string BlobNotFoundError = "The remote server returned an error: (404) Not Found.";
        private const string thumbnailFolder = "thumbnails/";
        private const string cropFolder = "crops/";
        private const string originalFolder = "originals/";
        private const string serviceName = "Image Processor";

        public static void ManageAzurePhotos(CloudBlobClient blobClient, string containerName, string cdnUrl)
        {
            DataStore dataStore = new DataStore();
            foreach (var itemMetaContent in dataStore.ContentEntities.ArticleMedias.Where(x => x.StatusId.Equals((int)StatusTypes.Submitted) || x.StatusId.Equals((int)StatusTypes.Updated) || x.StatusId.Equals((int)StatusTypes.DeletePending)).ToList())
            {
                try
                {
                    var item = dataStore.RepositoryEntities.RepositoryArticleMedias.FirstOrDefault(x => x.Identifier.Equals(itemMetaContent.Identifier));
                    if (item != null)
                    {
                        Console.WriteLine("Checking file:" + item.Identifier);
                        if (itemMetaContent == null)
                        {
                            Console.WriteLine("No content for file:" + item.Identifier);
                        }
                        else
                        {
                            Console.WriteLine("Status for file:" + item.Identifier + ":" + itemMetaContent.StatusId.ToString());
                            if (itemMetaContent.StatusId.Equals((int)StatusTypes.DeletePending))
                            {
                                CloudBlobContainer container = blobClient.GetContainerReference(containerName);
                                bool failureOccurred = false;
                                failureOccurred = failureOccurred ? failureOccurred : DeleteFile(container, string.Format("{0}{1}.png", thumbnailFolder, item.Identifier));
                                failureOccurred = failureOccurred ? failureOccurred : DeleteFile(container, string.Format("{0}{1}.png", cropFolder, item.Identifier));
                                failureOccurred = failureOccurred ? failureOccurred : DeleteFile(container, string.Format("{0}{1}.png", originalFolder, item.Identifier));

                                // Mark photo item with deleted status
                                if (!failureOccurred)
                                {
                                    itemMetaContent.StatusId = (int)StatusTypes.Deleted;
                                    itemMetaContent.LastPublishedDate = DateTime.Now;
                                    itemMetaContent.ThumbnailUrl = null;
                                    itemMetaContent.CropUrl = null;
                                    itemMetaContent.OriginalUrl = null;
                                }
                                else
                                {
                                    itemMetaContent.StatusId = (int)StatusTypes.ProcessError;
                                    itemMetaContent.LastPublishedDate = DateTime.Now;
                                }

                                dataStore.Put<DataStore, ArticleMediaViewModel, ArticleMedia>(dataStore.ContentEntities, new ArticleMediaViewModel(null, null, itemMetaContent), item.CreatedByUserId.Value, false, false);
                            }
                            else
                            {
                                CloudBlobContainer container = blobClient.GetContainerReference(containerName);
                                bool failureOccurred = false;

                                itemMetaContent.ThumbnailUrl = UploadFile(container, cdnUrl, containerName, string.Format("{0}{1}.png", thumbnailFolder, item.Identifier), item.ThumbnailData, ref failureOccurred);
                                itemMetaContent.CropUrl = UploadFile(container, cdnUrl, containerName, string.Format("{0}{1}.png", cropFolder, item.Identifier), item.CropData, ref failureOccurred);
                                itemMetaContent.OriginalUrl = UploadFile(container, cdnUrl, containerName, string.Format("{0}{1}.png", originalFolder, item.Identifier), item.Data, ref failureOccurred);

                                if (!failureOccurred)
                                {
                                    // update status to published
                                    itemMetaContent.StatusId = (int)StatusTypes.Published;
                                    itemMetaContent.LastPublishedDate = DateTime.Now;
                                }
                                else
                                {
                                    // update status to processing error
                                    itemMetaContent.StatusId = (int)StatusTypes.ProcessError;
                                }

                                dataStore.Put<DataStore, ArticleMediaViewModel, ArticleMedia>(dataStore.ContentEntities, new ArticleMediaViewModel(null, null, itemMetaContent), item.CreatedByUserId.Value, false, false);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    var ex2 = new MediaProcessorException(serviceName + " Error", ex);
                    Rally_MvvmC.Exceptions.Logger.LogException(ex2, serviceName);
                    Console.WriteLine(ex.GetBaseException().ToString());
                }
            }
        }

        private static bool DeleteFile(CloudBlobContainer container, string fileName)
        {
            try
            {
                CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
                if (blockBlob != null)
                {
                    blockBlob.Delete();
                }
            }
            catch (Exception ex)
            {
                if (!ex.Message.Equals(BlobNotFoundError))
                {
                    var ex2 = new MediaProcessorException(serviceName + " Error", ex);
                    Rally_MvvmC.Exceptions.Logger.LogException(ex2, serviceName);
                    Console.WriteLine(ex.GetBaseException().ToString());
                    return true;
                }
            }

            return false;
        }

        private static string UploadFile(CloudBlobContainer container, string cdnUrl, string containerName, string fileName, byte[] data, ref bool failureOccurred)
        {
            if (data != null)
            {
                try
                {
                    CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
                    Bitmap bitmap = null;
                    bitmap = new Bitmap(new MemoryStream(data));
                    var fileStream = new MemoryStream();
                    bitmap.Save(fileStream, ImageFormat.Png);
                    fileStream.Position = 0;
                    blockBlob.UploadFromStream(fileStream);
                    fileStream.Dispose();
                    bitmap.Dispose();
                }
                catch (Exception ex)
                {
                    var ex2 = new  MediaProcessorException(serviceName + " Error", ex);
                    Rally_MvvmC.Exceptions.Logger.LogException(ex2, serviceName);
                    Console.WriteLine(ex.GetBaseException().ToString());
                    failureOccurred = true;
                    return null;
                }

                return string.Concat(cdnUrl, containerName, "/", fileName);
            }

            return null;
        }
    }
}
